<script setup lang="ts">
import type { ScnBaseInfo } from "@/common/apis/scn/type"
import type { FormInstance, FormRules } from "element-plus"
import { addScenarioApi, searchScenarioBasic, updateScenarioApi } from "@/common/apis/scn"
import { getProjectId } from "@/common/utils/cache/local-storage"
import { formatDateTime } from "@/common/utils/datetime"
import { FormTypeEnum } from "@@/constants/other-keys"
import { ElMessage, ElMessageBox } from "element-plus"
import { cloneDeep, isEqual, isObject } from "lodash-es"
import { computed, ref, watch } from "vue"

interface Props {
  id: string | undefined
  dialogType: FormTypeEnum
  visible: boolean
}

const props = withDefaults(defineProps<Props>(), {
  dialogType: FormTypeEnum.VIEW
})
const emit = defineEmits(["closeDialog"])
const DEFAULT_FORM_DATA: ScnBaseInfo = {
  id: undefined,
  scnName: "",
  description: "",
  scnStartTime: "",
  scnEndTime: "",
  scnRunN: 1,
  simAreaRange: [
    { longitude: 0, latitude: 0, height: 0 },
    { longitude: 0, latitude: 0, height: 0 },
    { longitude: 0, latitude: 0, height: 0 },
    { longitude: 0, latitude: 0, height: 0 }
  ],
  useRandomSeed: false,
  randomSeed: -1,
  tTime: 0,
  simNetworkComm: false,
  timeRange: [],
  imageFile: '',
  ...(getProjectId() ? { pId: getProjectId() } : {})
}
const dialogVisible = ref<boolean>(false)
const formRef = ref<FormInstance | null>(null)
const formData = ref<ScnBaseInfo>(cloneDeep(DEFAULT_FORM_DATA))
const formRules: FormRules<ScnBaseInfo> = {
  scnName: [{ required: true, trigger: "blur", message: "请输入" }],
  timeRange: [{ required: true, trigger: "change", message: "请选择仿真时间" }],
  scnRunN: [{ required: true, trigger: "blur", message: "请输入" }]
}
const loading = ref<boolean>(false)
const detailLoading = ref<boolean>(false)
const isEdit = ref<boolean>(false)
const defaultFormData = ref<ScnBaseInfo>(cloneDeep(DEFAULT_FORM_DATA))

const textMap = computed(() => {
  if (props.dialogType === FormTypeEnum.CREATE) return "新建想定"
  else if (props.dialogType === FormTypeEnum.EDIT) return "编辑想定"
  else return "查看想定"
})
function getScnInfo() {
  detailLoading.value = true
  props.id
    && searchScenarioBasic(props.id)
      .then(({ data }) => {
        if (data) {
          formData.value = { ...data }
          formData.value.timeRange = [formData.value.scnStartTime, formData.value.scnEndTime]
          formData.value.simAreaRange.forEach(item => {
            item.height = Number(item.height)
            item.longitude = Number(item.longitude)
            item.latitude = Number(item.latitude)
          })
        } else {
          ElMessage("数据不存在")
        }
      })
      .finally(() => {
        detailLoading.value = false
      })
}
function showDialog() {
  formRef.value?.resetFields()
  isEdit.value = false
  detailLoading.value = false
  formData.value = cloneDeep(DEFAULT_FORM_DATA)
  if (props.dialogType !== FormTypeEnum.CREATE) {
    getScnInfo()
  }
}
function closeDialog() {
  formRef.value?.resetFields()
  emit("closeDialog", undefined)
}
function getParam() {
  const params = cloneDeep(formData.value)
  const propItems = ["id", "scnName", "description", "scnRunN", "simAreaRange", "useRandomSeed", "randomSeed", "tTime", "simNetworkComm", "pId", "engineId", "relationId"]
  const paramData = new FormData();
  Object.keys(params).forEach(key => {
    const value = params[key];
    if (propItems.indexOf(key) != -1 && value != null && value != undefined) {
      if (Array.isArray(value)) {
        value.forEach((subValue, i) => {
          if (isObject(subValue)) {
            Object.keys(subValue).forEach(prop => {
              paramData.append(key + `[${i}].${prop}`, subValue[prop])
            })
          } else {
            paramData.append(key + `[${i}]`, subValue)
          }
        })
      } else {
        paramData.append(key, value)
      }
    }
  })
  if (params.timeRange?.length == 2) {
    paramData.append("scnStartTime", params.timeRange[0])
    paramData.append("scnEndTime", params.timeRange[1])
  }
  params.imageFile = inFile.value
  return paramData;
}
function handleConfirm() {
  formRef.value?.validate(async (valid: boolean, fields) => {
    if (!valid) return console.error("表单校验不通过", fields)
    loading.value = true
    const api = props.dialogType == FormTypeEnum.CREATE ? addScenarioApi : updateScenarioApi
    const params = getParam()
    api(params)
      .then(() => {
        ElMessage.success("操作成功")
        emit("closeDialog", "refresh")
      })
      .finally(() => {
        loading.value = false
      })
  })
}
function handleCloseTip(done: () => void) {
  if (props.dialogType === FormTypeEnum.VIEW && !isEdit.value) {
    closeDialog()
    done()
    return
  }
  // 校验值是否相同
  if (isEqual(defaultFormData.value, formData.value)) {
    closeDialog()
    done()
    return
  }
  ElMessageBox.confirm("当前编辑未保存，是否确定关闭？").then(() => {
    done()
  })
}
function handleEdit() {
  defaultFormData.value = cloneDeep(formData.value)
  isEdit.value = true
}
function handleEditCancel() {
  isEdit.value = false
  getScnInfo()
}
function handleEditSave() {
  formRef.value?.validate(async (valid: boolean, fields) => {
    if (!valid) return console.error("表单校验不通过", fields)
    loading.value = true
    const params = getParam()
    updateScenarioApi(params)
      .then(() => {
        ElMessage.success("操作成功")
        isEdit.value = false
      })
      .finally(() => {
        loading.value = false
      })
  })
}
const fileList = ref<any>([])
const inFile = ref<any>(null)
const imageUrl = ref('')

const handleFileExceed = (files: any) => {
}
const handleFileChange = (uploadFile: any) => {
  fileList.value = [uploadFile];
  imageUrl.value = URL.createObjectURL(uploadFile.raw!);
  inFile.value = uploadFile.raw;
}

watch(
  () => [props.id, props.dialogType, props.visible],
  () => {
    dialogVisible.value = props.visible
    if (props.visible) {
      showDialog()
    }
  }
)
watch(
  () => [props.id, props.dialogType],
  () => {
    formData.value = cloneDeep(DEFAULT_FORM_DATA)
    defaultFormData.value = cloneDeep(formData.value)
    if (props.dialogType !== FormTypeEnum.CREATE) {
      getScnInfo()
    }
  }
)
</script>

<template>
  <el-drawer v-model="dialogVisible" direction="rtl" size="800px" @close-auto-focus="closeDialog" @close="closeDialog"
    :before-close="handleCloseTip" :show-close="false">
    <template #header>
      <div class="drawer-header">
        <h4>{{ textMap }}</h4>
        <el-space>
          <el-button v-if="isEdit" @click="handleEditCancel">
            取消保存
          </el-button>
          <el-button v-if="isEdit" type="primary" v-throttle="() => handleEditSave()">
            保存
          </el-button>
          <el-button v-if="!isEdit && props.dialogType == FormTypeEnum.VIEW" type="primary" @click="handleEdit">
            编辑
          </el-button>
        </el-space>
      </div>
    </template>
    <template #default>
      <el-form v-if="dialogType != FormTypeEnum.VIEW || isEdit" ref="formRef" :model="formData" :rules="formRules"
        width="600" label-width="120px" label-position="top" :close-on-click-modal="false" v-loading="detailLoading">
        <el-row :gutter="24">
          <el-col :span="12">
            <el-form-item label="想定名称" prop="scnName">
              <el-input v-model="formData.scnName" autocomplete="off" placeholder="请输入" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="仿真时间" prop="timeRange">
              <el-date-picker v-model="formData.timeRange" type="daterange" unlink-panels range-separator="至"
                value-format="YYYY-MM-DD HH:mm:ss" format="YYYY-MM-DD" start-placeholder="仿真开始时间"
                end-placeholder="仿真结束时间" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="仿真次数" prop="scnRunN">
              <el-input-number v-model="formData.scnRunN" :controls="false" class="sc-input-number" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="T时刻" prop="tTime">
              <el-input-number v-model="formData.tTime" :controls="false" class="sc-input-number" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="仿真区域" class="mt-3" />
        <el-form-item label="北" label-position="right" label-width="50px">
          <div class="item-range">
            <el-input-number v-model="formData.simAreaRange[0].longitude" placeholder="纬度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[0].latitude" placeholder="经度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[0].height" placeholder="高度" :controls="false" :precision="6"
              class="sc-input-number" />
          </div>
        </el-form-item>
        <el-form-item label="东" label-position="right" label-width="50px">
          <div class="item-range">
            <el-input-number v-model="formData.simAreaRange[1].longitude" placeholder="纬度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[1].latitude" placeholder="经度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[1].height" placeholder="高度" :controls="false" :precision="6"
              class="sc-input-number" />
          </div>
        </el-form-item>
        <el-form-item label="南" label-position="right" label-width="50px">
          <div class="item-range">
            <el-input-number v-model="formData.simAreaRange[2].longitude" placeholder="纬度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[2].latitude" placeholder="经度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[2].height" placeholder="高度" :controls="false" :precision="6"
              class="sc-input-number" />
          </div>
        </el-form-item>
        <el-form-item label="西" label-position="right" label-width="50px">
          <div class="item-range">
            <el-input-number v-model="formData.simAreaRange[3].longitude" placeholder="纬度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[3].latitude" placeholder="经度" :controls="false"
              :precision="6" class="sc-input-number" />
            <el-input-number v-model="formData.simAreaRange[3].height" placeholder="高度" :controls="false" :precision="6"
              class="sc-input-number" />
          </div>
        </el-form-item>
        <el-row>
          <el-form-item prop="useRandomSeed">
            <el-checkbox v-model="formData.useRandomSeed">
              是否使用随机种子
            </el-checkbox>
          </el-form-item>
          <el-form-item v-if="formData.useRandomSeed" label="随机种子" prop="scnRunN" label-position="right">
            <el-input-number v-model="formData.randomSeed" :controls="false" class="sc-input-number" />
          </el-form-item>
        </el-row>
        <el-form-item prop="simNetworkComm">
          <el-checkbox v-model="formData.simNetworkComm">
            是否使用仿真实体间网络通信
          </el-checkbox>
        </el-form-item>
        <el-form-item label="缩略图">
          <el-upload ref="UploadFileRef" class="avatar-uploader" v-model:file-list="fileList" :limit="1"
            :show-file-list="false" accept="image/png,image/jpeg,image/gif" :auto-upload="false"
            :on-exceed="handleFileExceed" :on-change="handleFileChange">
            <img v-if="imageUrl" :src="imageUrl" class="avatar" />
            <div v-else class="avatar-uploader-icon">
              <el-icon>
                <Plus />
              </el-icon>
              <span class="describe">点击上传缩略图</span>
            </div>
          </el-upload>
        </el-form-item>
        <el-form-item label="描述" prop="description" class="mt-3">
          <el-input v-model="formData.description" :rows="3" type="textarea" placeholder="请输入" maxlength="600" />
        </el-form-item>
      </el-form>

      <el-form v-else width="600" label-width="120px" :close-on-click-modal="false" v-loading="detailLoading"
        class="custom-view-form">
        <el-form-item label="想定名称：">
          {{ $getViewText(formData.scnName) }}
        </el-form-item>
        <el-form-item label="仿真时间：" prop="timeRange">
          {{ formData.timeRange ? `${formatDateTime(formData.timeRange[0], "YYYY-MM-DD")} -
          ${formatDateTime(formData.timeRange[1], "YYYY-MM-DD")}` : '' }}
        </el-form-item>
        <el-form-item label="仿真次数：" prop="scnRunN">
          {{ $getViewText(formData.scnRunN) }}
        </el-form-item>
        <el-form-item label="T时刻：" prop="tTime">
          {{ $getViewText(formData.tTime) }}
        </el-form-item>
        <el-form-item label="仿真区域：" class="mt-3" />
        <el-row>
          <el-form-item label="北：" label-position="right" label-width="120px">
            {{ `${Number(formData.simAreaRange[0].latitude).toFixed(6)},
            ${Number(formData.simAreaRange[0].longitude).toFixed(6)},
            ${Number(formData.simAreaRange[0].height).toFixed(6)}` }}
          </el-form-item>
          <el-form-item label="东：" label-position="right" label-width="120px">
            {{ `${Number(formData.simAreaRange[1].latitude).toFixed(6)},
            ${Number(formData.simAreaRange[1].longitude).toFixed(6)},
            ${Number(formData.simAreaRange[1].height).toFixed(6)}` }}
          </el-form-item>
          <el-form-item label="南：" label-position="right" label-width="120px">
            {{ `${Number(formData.simAreaRange[2].latitude).toFixed(6)},
            ${Number(formData.simAreaRange[2].longitude).toFixed(6)},
            ${Number(formData.simAreaRange[2].height).toFixed(6)}` }}
          </el-form-item>
          <el-form-item label="西：" label-position="right" label-width="120px">
            {{ `${Number(formData.simAreaRange[3].latitude).toFixed(6)},
            ${Number(formData.simAreaRange[3].longitude).toFixed(6)},
            ${Number(formData.simAreaRange[3].height).toFixed(6)}` }}
          </el-form-item>
        </el-row>
        <el-row>
          <el-form-item label="是否使用随机种子：" label-width="180px" prop="useRandomSeed">
            {{ formData.useRandomSeed ? "是" : "否" }}
          </el-form-item>
          <el-form-item v-if="formData.useRandomSeed" label="随机种子：" label-position="right">
            {{ $getViewText(formData.randomSeed) }}
          </el-form-item>
        </el-row>
        <el-form-item label="是否使用仿真实体间网络通信：" label-width="250px">
          {{ formData.simNetworkComm ? "是" : "否" }}
        </el-form-item>
        <el-form-item label="描述：" class="mt-3">
          {{ $getViewText(formData.description) }}
        </el-form-item>
      </el-form>
    </template>
    <template v-if="dialogType !== FormTypeEnum.VIEW" #footer>
      <div class="dialog-footer">
        <el-button plain @click="closeDialog">
          取 消
        </el-button>
        <el-button :loading="loading" type="primary" @click="handleConfirm">
          确 定
        </el-button>
      </div>
    </template>
    <template v-else #footer>
      <div class="dialog-footer">
        <el-button plain @click="closeDialog">
          关 闭
        </el-button>
      </div>
    </template>
  </el-drawer>
</template>

<style lang="scss" scoped>
.item-range {
  display: flex;

}

.upload-demo {
  width: 100% !important;
}

:deep(.el-upload.el-upload--text) {
  width: 100% !important;
}

:deep(.el-input-number .el-input__inner) {
  text-align: left !important;
}

.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}

.avatar-uploader .el-upload {
  border: 1px dashed #409EFF;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
  background-color: #ECF5FF;
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.avatar-uploader-icon {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 20px;
  width: 178px;
  height: 178px;

  .el-icon {
    font-size: 28px;
    color: #8c939d;
  }

  .describe {
    color: #409EFF;
  }
}
</style>
